﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection.Metadata;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Markup;
using Code4Bugs.Utils.Intercomm;
using Code4Bugs.Utils.Intercomm.Sockets;
using DataBase.DBmodels;
using DataBase.Utils;
using Google.Protobuf.WellKnownTypes;
using Microsoft.EntityFrameworkCore;
using MvvmHelpers;
using Newtonsoft.Json.Linq;
using NModbus;
using NModbus.Serial;
using Org.BouncyCastle.Utilities.Encoders;
using SuperSimpleTcp;
using static GreenXi.GlobalVariables;


namespace GreenXi.Help.Dam
{
    public class ModBus
    {
        public static List<string> port=new List<string>();
        public static double CurrentCoefficient1 = 0.1;
        public static double CurrentCoefficient2 = 0.001;
        public static double CurrentCoefficient3 = 0.001;
        public static double CurrentCoefficient4 = 0.001;

        public static double EnergyCoefficient = 0.01;

        public static double HumidityCoefficient = 0.1;
        private static SimpleTcpServer Server;
        public static object Lock = new object();
        public static void Init()
        {
            try
            {

                Server = new SimpleTcpServer(GlobalVariables.ServoMotorIp1, GlobalVariables.TCPPort);
                Server.Events.DataReceived += DataReceived;
                Server.Events.ClientConnected += ClientConnected;
                Server.Settings.NoDelay = true;
                Server.Keepalive.EnableTcpKeepAlives = true;
                Server.Settings.MutuallyAuthenticate = false;
                Server.Settings.AcceptInvalidCertificates = true;
                // 启动服务器
                Server.Start();

            }
            catch (Exception ex)
            {
                Helpers.Logger.Instance.Error(ex, $"设置Modbus服务失败IP{GlobalVariables.ServoMotorIp1} port{port}");
                PoliceStr = $"{System.Enum.GetName(typeof(CallPoliceStatus), 40)} 异常信息：{ex.Message}";
                GlobalVariables.CallPolice = 40;
            }
        }

        public static   bool Send(string str)
        {
            if (port.Count!=0)
            {
               var strs = ConvertHexStringToByteArray(str);
                foreach (string s in port) {
                    Server.Send(s, strs);
                }
                Helpers.Logger.Instance.Infomation($"发送的数据{str}");
                Thread.Sleep(GlobalVariables.ServoMotorSlaveAddress);
            }
          
            return true;
        }
        static void ClientConnected(object? sender, ConnectionEventArgs e)
        {
            if ((DateTime.Now - GlobalVariables.LastTime) > TimeSpan.FromHours(1))
            {
                port.Clear();
            }
            port.Add(e.IpPort);
            Helpers.Logger.Instance.Infomation($"从站连接成功{e.IpPort}");
            GlobalVariables.LastTime=DateTime.Now;
        }
        

        static void DataReceived(object sender, DataReceivedEventArgs e)
        {
             var bytesReceived = e.Data.Array;
            string hexResponse = BitConverter.ToString(bytesReceived, 0, e.Data.Count).Replace("-", " ");
            Helpers.Logger.Instance.Infomation($"收到的数据{hexResponse}");
            Handle(hexResponse);
        }

        /// <summary>
        /// 处理数据
        /// </summary>
        /// <param name="str"></param>
        public static void Handle(string str)
        {
            if (str.Length < 100)
            {
                return;
            }
            var model = GetModel(str);

            CraftView craft;

               var Gateway = GlobalVariables.GatewayList.Where(x => x.IPId == model.GatewayId).FirstOrDefault();
            if (Gateway == null) {
                return;
            }

            int Type = 1;
            craft = GlobalVariables.CraftViewList.Where(x => x.NodeId == model.NodeId && x.StationNode == model.StationNode && x.GateWayId == Gateway.Id).FirstOrDefault();
            if (craft == null) {
                Type = 2;
                model.CRC16 = "Humidity";
                craft = GlobalVariables.CraftViewList2.Where(x => x.NodeId == model.NodeId && x.StationNode == model.StationNode && x.GateWayId == Gateway.Id).FirstOrDefault();
                if (craft == null)
                {
                    Type = 3;
                    craft = GlobalVariables.CraftViewList3.Where(x => x.NodeId == model.NodeId && x.StationNode == model.StationNode && x.GateWayId == Gateway.Id).FirstOrDefault();
                }
            }
            
              
                
           

            if (craft == null)
            {
                return;
            }


            craft.Status= model.Status;
        
            double VoltageRatio = craft.VoltageRatio == null ? 1 : craft.VoltageRatio.Value;
            double CurrentRatio = craft.CurrentRatio == null ? 1 : craft.CurrentRatio.Value;

            //电流
            //获取电流和总功率
            if (model.CRC16 == "Current")
            {
                // 将十六进制字符串转换为十进制并赋值
                craft.Voltage_A = Math.Round(model.Voltage_A * VoltageRatio* CurrentCoefficient1, 1);
                craft.Voltage_B = Math.Round(model.Voltage_B * VoltageRatio* CurrentCoefficient1, 1);
                craft.Voltage_C = Math.Round(model.Voltage_C * VoltageRatio*CurrentCoefficient1, 1);

                craft.Electric_A = Math.Round((model.Electric_A)* CurrentRatio * CurrentCoefficient2,1);
                craft.Electric_B = Math.Round((model.Electric_B)* CurrentRatio * CurrentCoefficient2,1);
                craft.Electric_C = Math.Round((model.Electric_C)* CurrentRatio * CurrentCoefficient2,1);

                craft.Power_A = Math.Round((model.Power_A) * VoltageRatio* CurrentRatio * CurrentCoefficient3, 1);
                craft.Power_B = Math.Round((model.Power_B) * VoltageRatio*CurrentRatio * CurrentCoefficient3, 1);
                craft.Power_C = Math.Round((model.Power_C) * VoltageRatio*CurrentRatio * CurrentCoefficient3, 1);


                craft.PowerFactor_A = Math.Round((model.PowerFactor_A) * CurrentCoefficient4, 1);
                craft.PowerFactor_B = Math.Round((model.PowerFactor_B) * CurrentCoefficient4, 1);
                craft.PowerFactor_C = Math.Round((model.PowerFactor_C) * CurrentCoefficient4, 1);

                GlobalVariables.CraftViewList = GlobalVariables.CraftViewList;
            }
            ///获取实时电量
            if (model.CRC16 == "Ele")
            {
                var EnergyLong = CombineHexStringsToLong(model.Energy_High, model.Energy_low);
                craft.Energy = Math.Round(EnergyLong * VoltageRatio * CurrentRatio * EnergyCoefficient,1);
                GlobalVariables.CraftViewList = GlobalVariables.CraftViewList;
            }//温度
            if (model.CRC16 == "Humidity")
            {
               
                craft.Humidity_A = Math.Round((model.Humidity_A)* HumidityCoefficient, 1);
                craft.Humidity_B = Math.Round((model.Humidity_B)* HumidityCoefficient, 1);
                craft.Humidity_C = Math.Round((model.Humidity_C)* HumidityCoefficient, 1);
                if(Type==2)
                    GlobalVariables.CraftViewList2 = GlobalVariables.CraftViewList2;

                if (Type == 3)
                    GlobalVariables.CraftViewList3 = GlobalVariables.CraftViewList3;
            }

            //存到日志表里
            MyDbContext myDbContext = new();
            productiondatalog log = new productiondatalog
            {
             CraftId=craft.Id,
             CraftName=craft.Project,
             Voltage_A=craft.Voltage_A,
             Voltage_B=craft.Voltage_B,
             Voltage_C=craft.Voltage_C,
             Electric_A=craft.Electric_A,
             Electric_B=craft.Electric_B,
             Electric_C=craft.Electric_C,
             Power_A=craft.Power_A,
             Power_B=craft.Power_B,
             Power_C=craft.Power_C,
             PowerFactor_A=craft.PowerFactor_A,
             PowerFactor_B=craft.PowerFactor_B,
             PowerFactor_C=craft.PowerFactor_C,
             Humidity_A=craft.Humidity_A,
             Humidity_B =craft.Humidity_B,
             Humidity_C=craft.Humidity_C,
             Energy=craft.Energy,
            };
         
             myDbContext.Add(log);
            myDbContext.SaveChanges();
            //电能
        }
        /// <summary>
        /// 获取电流
        /// </summary>
        public static string ElectricCurrentStr = " 03 00 00 00 17";

        /// <summary>
        /// 获取用电量
        /// </summary>
        public static string ElectricEnergyStr = " 03 00 1D 00 02";


        /// <summary>
        /// 获取温度
        /// </summary>
        public static string TemperatureStr = " 03 00 00 00 02";

        /// <summary>
        /// 获取变压器温度
        /// </summary>
        public static string TransformerTemperatureStr = " 03 00 00 00 03";

        /// <summary>
        /// 获取实时电流
        /// </summary>
        /// <param name="ModelID"></param>
        /// <returns></returns>
        public static  bool GetElectricCurrent(string NodeId,string IPId, string StationNode)
        {
            //拼接命令
            string str = InsertSpaceEveryTwoChars($"{IPId}{NodeId}08")+" ";
            str += StationNode+ElectricCurrentStr+ CRCCalc(HexStringToByteArray(StationNode + ElectricCurrentStr));
            bool result=  Send(str);
            return result;
        }

        /// <summary>
        /// 获取用电量
        /// </summary>
        /// <param name="ModelID"></param>
        /// <returns></returns>
        public static bool GetElectricEnergy(string NodeId,string IPId, string StationNode)
        {
            //拼接命令
            string str = InsertSpaceEveryTwoChars($"{IPId}{NodeId}08") + " ";
            str += StationNode+ElectricEnergyStr+ CRCCalc(HexStringToByteArray(StationNode + ElectricEnergyStr));
            bool result = Send(str);
            return result;
        }

        /// <summary>
        /// 获取温湿度
        /// </summary>
        /// <param name="ModelID"></param>
        /// <returns></returns>
        public static bool GetTemperature(string NodeId, string IPId, string StationNode)
        {
            //拼接命令
            string str = InsertSpaceEveryTwoChars($"{IPId}{NodeId}08") + " ";
            str += StationNode + TemperatureStr + CRCCalc(HexStringToByteArray(StationNode + TemperatureStr));
            bool result = Send(str);
            return result;
        }

        /// <summary>
        /// 获取变压器温度
        /// </summary>
        /// <param name="ModelID"></param>
        /// <returns></returns>
        public static bool GetTransformerTemperature(string NodeId, string IPId, string StationNode)
        {
            //拼接命令
            string str = InsertSpaceEveryTwoChars($"{IPId}{NodeId}08") + " ";
            str += StationNode + TransformerTemperatureStr + CRCCalc(HexStringToByteArray(StationNode + TransformerTemperatureStr));
            bool result = Send(str);
            return result;
        }

        /// <summary>
        /// 把获取到的字符串转成需要的数据
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static ElectricityModel GetModel(string str)
        {
            ElectricityModel model = new ElectricityModel();

            var byteData = HexStringToByteArray(str);
            var parsedData = Parse(byteData);
             model.NodeId = parsedData.RemoteTerminalId;
            model.GatewayId = parsedData.GatewayId;
            model.Status = parsedData.IsOnline ? 1 : 0;
            model.StationNode = parsedData.StationNode;
            //电压电流参数
            if (parsedData.PayloadLength > 20)
            {
                model.CRC16 = "Current";
                model.Voltage_A = parsedData.PayloadDecimals[3];
                model.Voltage_B = parsedData.PayloadDecimals[4];
                model.Voltage_C = parsedData.PayloadDecimals[5];
                model.Electric_A = parsedData.PayloadDecimals[6];
                model.Electric_B = parsedData.PayloadDecimals[7];
                model.Electric_C = parsedData.PayloadDecimals[8];


                model.Power_A = parsedData.PayloadDecimals[11] > 32500? 65535 - parsedData.PayloadDecimals[11]: parsedData.PayloadDecimals[11];
                model.Power_B = parsedData.PayloadDecimals[12] > 32500? 65535 - parsedData.PayloadDecimals[12]: parsedData.PayloadDecimals[12];
                model.Power_C = parsedData.PayloadDecimals[13] > 32500? 65535 - parsedData.PayloadDecimals[13]: parsedData.PayloadDecimals[13];


                model.PowerFactor_A = parsedData.PayloadDecimals[23]> 32500 ? 65535- parsedData.PayloadDecimals[23] : parsedData.PayloadDecimals[23];
                model.PowerFactor_B = parsedData.PayloadDecimals[24] > 32500 ? 65535 - parsedData.PayloadDecimals[24] : parsedData.PayloadDecimals[24]; ;
                model.PowerFactor_C = parsedData.PayloadDecimals[25] > 32500 ? 65535 - parsedData.PayloadDecimals[25] : parsedData.PayloadDecimals[25]; ;

            }//电能参数
            else if (parsedData.PayloadLength ==9)
            {
                model.CRC16 = "Ele";
                model.Energy_High = parsedData.PayloadDecimals[3];
                model.Energy_low = parsedData.PayloadDecimals[4];
                model.Humidity_A = parsedData.PayloadDecimals[3];
                model.Humidity_B = parsedData.PayloadDecimals[4];
            }
            else if (parsedData.PayloadLength == 11)//温度
            {
                model.CRC16 = "Humidity";
                model.Humidity_A = parsedData.PayloadDecimals[3];
                model.Humidity_B = parsedData.PayloadDecimals[4];
                model.Humidity_C = parsedData.PayloadDecimals[5];
            }
            return model;
        }
        public static string RemoveSpaces(string input)
        {
            return new string(input.Where(c => !char.IsWhiteSpace(c)).ToArray());
        }
        /// <summary>
        /// 两两加空格
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string InsertSpaceEveryTwoChars(string input)
        {
            return string.Join(" ", Enumerable.Range(0, input.Length / 2)
                .Select(i => input.Substring(i * 2, 2)));
        }

        /// <summary>
        /// 字符串转字节组
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static byte[] ConvertHexStringToByteArray(string hex)
        {
            string[] hexValues = hex.Split(' ');
            byte[] bytes = new byte[hexValues.Length];
            try
            {
            
                for (int i = 0; i < hexValues.Length; i++)
                {
                    // 将每个十六进制字符串转换为字节
                    bytes[i] = Convert.ToByte(hexValues[i], 16);
                }

            }
            catch(Exception e) 
            {
                var aa = e.Message;
            }
            // 按空格分割十六进制字符串
         
           
            return bytes;
        }

        /// <summary>
        /// 字符串转字数组
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static string[] ConvertHexStringToStrArray(string hex)
        {
            // 按空格分割十六进制字符串
            string[] hexValues = hex.Split(' ');
            string[] strings = new string[hexValues.Length/2];

            for (int i = 0; i < hexValues.Length; i++)
            {
                // 将每个十六进制字符串转换为字节
                strings[i/2] += hexValues[i];
            }

            return strings;
        }

        /// <summary>
        /// 将十六进制字符串转换为十进制整数
        /// </summary>
        /// <param name="hex">十六进制字符串</param>
        /// <returns>十进制整数</returns>
        public static int HexToDecimal(string hex)
        {
            return Convert.ToInt32(hex, 16);
        }
        public static long CombineHexStringsToLong(int high16Bits, int low16Bits)
        {
            // 将16进制字符串解析为整数

            // 将高16位左移16位，然后与低16位进行按位或操作
            return ((long)high16Bits << 16) | low16Bits;
        }


        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="num"></param>

        public class ElectricityModel
        {
            /// <summary>
            /// 电表ID
            /// </summary>
            public string NodeId;

            public string GatewayId;

            
            public string StationNode;

            public string CRC16;

            public int Status;

            /// <summary>
            /// 电压
            /// </summary>
            public double Voltage_A;
            public double Voltage_B;
            public double Voltage_C;


            //电流
            public double Electric_A;
            public double Electric_B;
            public double Electric_C;

            //功率
            public double Power_A;
            public double Power_B;
            public double Power_C;

            //功率yinshu2
            public double PowerFactor_A;
            public double PowerFactor_B;
            public double PowerFactor_C;

            //电能高低位数
            public int Energy_High;
            public int Energy_low;

            public double Humidity_A;
            public double Humidity_B;
            public double Humidity_C;

            public double Energy;
        }

        #region 解析数据

        public static GatewayData Parse(byte[] data)
        {
            if (data == null || data.Length < 27) // 最小合法长度校验
                throw new ArgumentException("Invalid data format");

            var result = new GatewayData();
            int index = 0;

            // 协议版本 (1 byte)
            result.ProtocolVersion = data[index++];

            // 命令字 (1 byte)
            result.Command = data[index++];

            // 网关ID (4 bytes)
            result.GatewayId = BitConverter.ToString(data, index, 4).Replace("-", "");
            index += 4;

            // 远程终端ID (4 bytes)
            result.RemoteTerminalId = BitConverter.ToString(data, index, 4).Replace("-", "");
            index += 4;

            // 短ID (2 bytes)
            result.ShortId = BitConverter.ToUInt16(data, index);
            index += 2;

            // 通道 (1 byte)
            result.Channel = data[index++];

            // SNR (1 byte)
            result.Snr = data[index++];

            // RSS信号强度 (2 bytes)
            Array.Copy(data, index, result.Rss, 0, 2);
            index += 2;

            // NC (2 bytes) - 保留字段
            Array.Copy(data, index, result.Nc, 0, 2);
            index += 2;

            // 时间戳 (4 bytes Unix时间戳)
            byte[] timestampBytes = new byte[4];
            Array.Copy(data, index, timestampBytes, 0, 4);
            if (BitConverter.IsLittleEndian) Array.Reverse(timestampBytes); // 转大端序
            uint unixTimestamp = BitConverter.ToUInt32(timestampBytes, 0);
            result.Timestamp = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).DateTime;
            index += 4;

            // 终端在线状态 (1 byte)
            result.IsOnline = data[index++] == 0x00;

            // 终端入网数 (2 bytes)
            result.ConnectedTerminals = BitConverter.ToUInt16(data, index);
            index += 2;

            byte[] payloadLengthBytes = new byte[2];
            Array.Copy(data, index, payloadLengthBytes, 0, 2);
            if (BitConverter.IsLittleEndian) Array.Reverse(payloadLengthBytes);
            result.PayloadLength = BitConverter.ToUInt16(payloadLengthBytes, 0);
            index += 2;

            // 有效数据
            result.PayloadData = new byte[result.PayloadLength];
            Array.Copy(data, index, result.PayloadData, 0, result.PayloadLength);
            index += result.PayloadLength;

            // 将每两个字节转换为一个整数（大端序）
            result.PayloadDecimals = new List<int>();
            result.PayloadDecimals.Add(0);
            result.PayloadDecimals.Add(0);
            result.PayloadDecimals.Add(0);
            for (int i = 3; i < result.PayloadData.Length; i += 2)
            {
                if (i + 1 >= result.PayloadData.Length)
                    throw new ArgumentException("Payload data has odd length.");

                int value = (result.PayloadData[i] << 8) | result.PayloadData[i + 1];
                result.PayloadDecimals.Add(value);
            }

            // 站点节点取第一个字节的两位十六进制表示
            result.StationNode = result.PayloadData.Length > 0 ?
                                 result.PayloadData[0].ToString("X2") :
                                 "00";

            //// 将每个字节转换为十进制数值
            //result.PayloadDecimals = result.PayloadData.Select(b => (int)b).ToList();
            //result.StationNode = result.PayloadDecimals[0].ToString("00");
            return result;
        }
        public class GatewayData
        {
            // 协议版本 (1 byte)
            public byte ProtocolVersion { get; set; }

            // 网关命令字 (1 byte)
            public byte Command { get; set; }

            // 网关ID (4 bytes)
            public string GatewayId { get; set; }

            // 远程终端ID (4 bytes)
            public string RemoteTerminalId { get; set; }

            // 短ID (2 bytes)
            public ushort ShortId { get; set; }

            // 通道 (1 byte)
            public byte Channel { get; set; }

            // SNR (1 byte)
            public byte Snr { get; set; }

            // RSS信号强度 (2 bytes)
            public byte[] Rss { get; set; } = new byte[2];

            // NC (2 bytes) - 保留字段
            public byte[] Nc { get; set; } = new byte[2];

            // 时间戳 (4 bytes Unix时间戳)
            public DateTime Timestamp { get; set; }

            // 终端在线状态 (1 byte)
            public bool IsOnline { get; set; }

            // 终端入网数 (2 bytes)
            public ushort ConnectedTerminals { get; set; }

            // 有效数据长度 (1 byte)
            public ushort PayloadLength { get; set; }

            // 有效载荷数据 (长度由 PayloadLength 决定)
            public byte[] PayloadData { get; set; }
            /// <summary>
            /// 从站节点
            /// </summary>
            public string StationNode { get; set; }


            // 新增：存储每个字节的十进制数值的数组
            public List<int> PayloadDecimals { get; set; } = new List<int>();
        }

        #endregion  

        // 辅助方法：将十六进制字符串转换为字节数组
        public static byte[] HexStringToByteArray(string hex)
        {
            return hex.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                      .Select(s => byte.Parse(s, NumberStyles.HexNumber))
                      .ToArray();
        }

        /// <summary>
        /// CRC校验，参数data为byte数组
        /// </summary>
        /// <param name="data">校验数据，字节数组</param>
        /// <returns>字节0是高8位，字节1是低8位</returns>
        public static string CRCCalc(byte[] data)
        {
            //crc计算赋初始值
            int crc = 0xffff;
            for (int i = 0; i < data.Length; i++)
            {
                crc = crc ^ data[i];
                for (int j = 0; j < 8; j++)
                {
                    int temp;
                    temp = crc & 1;
                    crc = crc >> 1;
                    crc = crc & 0x7fff;
                    if (temp == 1)
                    {
                        crc = crc ^ 0xa001;
                    }
                    crc = crc & 0xffff;
                }
            }
            //CRC寄存器的高低位进行互换
            byte[] crc16 = new byte[2];
            //CRC寄存器的高8位变成低8位，
            crc16[1] = (byte)((crc >> 8) & 0xff);
            //CRC寄存器的低8位变成高8位
            crc16[0] = (byte)(crc & 0xff);

            var result = " "+BitConverter.ToString(new[] { crc16[0] })+" "+ BitConverter.ToString(new[] { crc16[1] });
            return result;
        }
    }
}
